package com.atguigu.gmall.order.controller;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.cart.client.CartFeignClient;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.util.AuthContextHolder;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.user.UserAddress;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.user.client.UserFeignClient;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Author: zm
 * @Date: 2021/8/24 19:35
 */
@RestController
@RequestMapping("api/order")
public class OrderApiController {

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private CartFeignClient cartFeignClient;

    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private ProductFeignClient productFeignClient;


    //  映射路径：给web-all 使用！ web-all 页面渲染的！
    //  需要在后台存储 detailArrayList ， userAddressList, totalNum, totalAmount
    @GetMapping("auth/trade")
    public Result trade(HttpServletRequest request) {

        String userId = AuthContextHolder.getUserId(request);
        List<UserAddress> userAddressList = userFeignClient.findUserAddressListByUserId(Long.parseLong(userId));

        List<CartInfo> cartInfoList = cartFeignClient.getCartCheckedList(userId);

        int totalNum = 0;

        List<OrderDetail> detailArrayList = new ArrayList<>();
        for (CartInfo cartInfo : cartInfoList) {
            OrderDetail orderDetail = new OrderDetail();

            orderDetail.setCreateTime(new Date());
            orderDetail.setSkuId(cartInfo.getSkuId());
            orderDetail.setSkuName(cartInfo.getSkuName());
            orderDetail.setSkuNum(cartInfo.getSkuNum());
            orderDetail.setImgUrl(cartInfo.getImgUrl());
            orderDetail.setOrderPrice(cartInfo.getSkuPrice());

            totalNum += orderDetail.getSkuNum();

            detailArrayList.add(orderDetail);
        }

        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderDetailList(detailArrayList);
        orderInfo.sumTotalAmount(); // 可以直接获取总金额

        Map<String, Object> map = new HashMap<>();
        map.put("detailArrayList", detailArrayList);
        map.put("userAddressList", userAddressList);

        map.put("totalNum", totalNum);
        map.put("totalAmount", orderInfo.getTotalAmount());

        map.put("tradeNo", orderInfoService.createTradeNo(userId));

        return Result.ok(map);
    }

    /**
     * 保存订单
     *
     * @param orderInfo
     * @param request
     * @return
     */
    // http://api.gmall.com/api/order/auth/submitOrder?tradeNo=null
    @PostMapping("auth/submitOrder")
    public Result submitOrder(@RequestBody OrderInfo orderInfo, HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request);
        String tradeNo = request.getParameter("tradeNo");

        boolean flag = orderInfoService.checkTradeNo(tradeNo, userId);
        if (!flag) {
            return Result.fail().message("请勿重复提交,请刷新后再提交");
        }

        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();

        List<CompletableFuture> runList = new ArrayList<>();
        List<String> errorList = new ArrayList<>();
        for (OrderDetail orderDetail : orderDetailList) {

            CompletableFuture<Void> stockCompletableFuture = CompletableFuture.runAsync(() -> {
                boolean result = orderInfoService.checkStock(orderDetail.getSkuId(), orderDetail.getSkuNum());
                if (!result) {
                    errorList.add(orderDetail.getSkuName() + "库存不足!");
                }
            }, threadPoolExecutor);
            runList.add(stockCompletableFuture);

            CompletableFuture<Void> priceCompletableFuture = CompletableFuture.runAsync(() -> {
                BigDecimal skuPrice = productFeignClient.getSkuPrice(orderDetail.getSkuId());
                if (skuPrice.compareTo(orderDetail.getOrderPrice()) != 0) {
                    cartFeignClient.loadCartToCache(userId);
                    errorList.add(orderDetail.getSkuName() + "价格有变动");
                }
            }, threadPoolExecutor);
            runList.add(priceCompletableFuture);
        }

        CompletableFuture.allOf(runList.toArray(new CompletableFuture[runList.size()])).join();
        if (!CollectionUtils.isEmpty(errorList)) {
            return Result.fail().message(StringUtils.join(errorList, ","));
        }

        orderInfoService.deleteTradeNo(userId);
        orderInfo.setUserId(Long.parseLong(userId));
        Long orderId = orderInfoService.submitOrder(orderInfo);
        return Result.ok(orderId);
    }


    /**
     * 切分订单
     *
     * @param request
     * @return
     */
    // http://order.gmall.com/api/order/orderSplit?orderId=xxx&wareSkuMap=xxx  http://localhost:8204/api/order/orderSplit
    // String resultJson = HttpclientUtil.doPost(ORDER_URL, map);
    @PostMapping("orderSplit")
    public String orderSplit(HttpServletRequest request) {
        String orderId = request.getParameter("orderId");
        String wareSkuMap = request.getParameter("wareSkuMap");

        List<OrderInfo> orderInfos = orderInfoService.orderSplit(Long.parseLong(orderId), wareSkuMap);

        List<Map> list = new ArrayList<>();
        for (OrderInfo orderInfo : orderInfos) {
            Map<String, Object> map = orderInfoService.orderInfoToMap(orderInfo);
            list.add(map);
        }

        return JSON.toJSONString(list);
    }


    /**
     * 内部调用获取订单
     *
     * @param orderId
     * @return
     */
    @GetMapping("inner/getOrderInfo/{orderId}")
    public OrderInfo getOrderInfo(@PathVariable(value = "orderId") Long orderId) {
        return orderInfoService.getOrderInfo(orderId);
    }


    /**
     * 保存订单
     *
     * @param orderInfo
     * @return
     */
    @PostMapping("inner/seckill/submitOrder")
    public Long submitOrder(@RequestBody OrderInfo orderInfo) {
        return orderInfoService.submitOrder(orderInfo);
    }

}
